package china.lzy.config.interceptor;

import china.lzy.exception.AuthErrException;
import china.lzy.exception.ParamErrorException;
import china.lzy.utils.AppJwtUtil;
import china.lzy.utils.anno.Authorization;
import china.lzy.utils.anno.NoAuthorization;
import io.jsonwebtoken.Claims;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


/**
 * @author ：lzy
 * @ Date       ：Created in 10:19 2021/8/10
 * @ Description：权限拦截器
 */

@Log4j2
public class AuthInterceptor implements HandlerInterceptor {
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
            return true;
        }
        if (!(handler instanceof HandlerMethod)) {
            return false;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //如果不需要权限就放行
        if (handlerMethod.hasMethodAnnotation(NoAuthorization.class)) {
            return true;
        }
        String token = request.getHeader("Authorization");
        if (StringUtils.isBlank(token)) {
            throw new ParamErrorException("Token不存在!");
        }
        //获取token的信息
        // TODO  注意这里是否解析过期的时候是否会报错
        Claims claimsBody = AppJwtUtil.getClaimsBody(token);
        //先从Redis获取  TOKEN_USERID_
        String redisToken = (String) redisTemplate.opsForValue().get("TOKEN_USERID_" + claimsBody.get("userid"));
        //如果 redis中的和传过来的不一样,就判定失效
        if (redisToken != null && !redisToken.equals(token)) {
            throw new ParamErrorException("Token已经过期!");
        }
        //如果需要权限就拦截a
        if (handlerMethod.hasMethodAnnotation(Authorization.class)) {
            List<String> role = (List<String>) claimsBody.get("role");
            //获取注解上的值,如果是权限就要权限,只要包含了权限就可以
            Authorization methodAnnotation = handlerMethod.getMethodAnnotation(Authorization.class);
            String[] authCode = methodAnnotation.value();
            for (int i = 0; i < authCode.length; i++) {
                if (role.contains(authCode[i])) {
                    return true;
                }
            }

        } else {
            throw new AuthErrException("权限不足");
        }
        throw new AuthErrException("权限不足");
    }
}
